﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;
using System.Text;
using Abp.Linq.Extensions;
using System.Threading.Tasks;
using System.Data.Entity;
using Abp.AutoMapper;
using MyCompanyName.AbpZeroTemplate.Prm.Project.Dto;
using Abp.Application.Services.Dto;
using MyCompanyName.AbpZeroTemplate.Prm.Authorization;
using MyCompanyName.AbpZeroTemplate.Prm.Admin;
using Abp.Domain.Repositories;
using MyCompanyName.AbpZeroTemplate.Gantt;
using System.Dynamic;
using MyCompanyName.AbpZeroTemplate.Authorization.Users.Dto;
using MyCompanyName.AbpZeroTemplate.Authorization.Users;
using System.Web;
using System.IO;
using Abp.Runtime.Session;
using MyCompanyName.AbpZeroTemplate.Prm.Project.ProjectTaskExport;
using Abp.Domain.Uow;
using Aspose.Words;

namespace MyCompanyName.AbpZeroTemplate.Prm.Project
{
    public class ProjectTaskAppService : AbpZeroTemplateAppServiceBase, IProjectTaskAppService
    {
        private readonly ProjectTaskManager _projectTaskManager;
        private readonly ProjectManager _projectManager;
        private readonly IRepository<Product, int> _productRepository;
        private readonly SubstanceManager _substanceManager;
        private readonly PermissionService _permissionService;
        private readonly MailManager _mailManager;
        private readonly OperationLogManager operationLogManager;

        private readonly IRepository<Quan, int> _quanRepository;
        private readonly IRepository<TaskQuan, int> _taskQuanRepository;

        private readonly IRepository<UserQuan, int> _UserQuanRepository;


        public ProjectTaskAppService(
                    IRepository<Quan, int> quanRepository,
        IRepository<TaskQuan, int> taskQuanRepository,
            ProjectTaskManager projectTaskManager,
            ProjectManager projectManager,
            IRepository<Product, int> productRepository,
            SubstanceManager substanceManager,
            PermissionService permissionService,
            IRepository<UserQuan, int> userQuanRepository,
            MailManager mailManager,
             OperationLogManager _operationLogManager)
        {
            _quanRepository = quanRepository;
            _taskQuanRepository = taskQuanRepository;
            _UserQuanRepository = userQuanRepository;
            _projectTaskManager = projectTaskManager;
            _projectManager = projectManager;
            _productRepository = productRepository;
            _substanceManager = substanceManager;
            _permissionService = permissionService;
            _mailManager = mailManager;
            operationLogManager = _operationLogManager;
        }


        /// <summary>
        /// 导入问题
        /// </summary>
        /// <returns></returns>
        public GetImportOutPut Import()
        {
            var projectId = HttpContext.Current.Request.Form["ProjectId"];
            var file = HttpContext.Current.Request.Files[0];
            if (file.ContentLength == 0)
            {
                throw new Abp.UI.UserFriendlyException("系统提示", "文件为空");
            }
            var fileBase = new HttpPostedFileWrapper(file) as HttpPostedFileBase;
            var extension = System.IO.Path.GetExtension(fileBase.FileName);
            if (extension != ".doc" && extension != ".docx")
            {
                throw new Abp.UI.UserFriendlyException("系统提示", "文件类型不正确");
            }

            var webPath = System.Web.HttpContext.Current.Request.PhysicalApplicationPath;

            var path = webPath + @"upload\" + fileBase.FileName;
            fileBase.SaveAs(path);

            WordHelper helper = new WordHelper();
            var text = helper.ToText(path);
            var tasks = Get(text);

            GetImportOutPut outPut = new GetImportOutPut();
            outPut.task = tasks;

            List<GetProjectTaskTreeOutPut> tree = new List<GetProjectTaskTreeOutPut>();


            var routes = tasks.GroupBy(x => x.Route).Select(x => x.Key);

            foreach (var item in routes)
            {
                var route = new GetProjectTaskTreeOutPut()
                {
                    id = Guid.NewGuid().ToString(),
                    leaf = tasks.Where(x => x.Route == item).Count() > 0 ? false : true,
                    parentId = "0",
                    text = item,
                    children = new List<GetProjectTaskTreeOutPut>()
                };
                tree.Add(route);
                var steps = tasks.Where(x => x.Route == item).GroupBy(x => x.Step).Select(x => x.Key);
                foreach (var s in steps)
                {
                    var step = new GetProjectTaskTreeOutPut()
                    {
                        id = Guid.NewGuid().ToString(),
                        leaf = tasks.Where(x => x.Step == s && x.Route == item).Count() > 0 ? false : true,
                        parentId = route.id,
                        text = s,
                        children = new List<GetProjectTaskTreeOutPut>()
                    };
                    route.children.Add(step);
                    var depts = tasks.Where(x => x.Step == s && x.Route == item).GroupBy(x => x.Dept).Select(x => x.Key);
                    foreach (var d in depts)
                    {
                        var aspect = new GetProjectTaskTreeOutPut()
                        {
                            id = Guid.NewGuid().ToString(),
                            leaf = tasks.Where(x => x.Route == item && x.Step == s && x.Dept == d).Count() > 0 ? false : true,
                            parentId = step.id,
                            text = d,
                            children = new List<GetProjectTaskTreeOutPut>()
                        };
                        step.children.Add(aspect);
                        var qus = tasks.Where(x => x.Route == item && x.Step == s && x.Dept == d);
                        foreach (var q in qus)
                        {
                            var qs = new GetProjectTaskTreeOutPut()
                            {
                                id = Guid.NewGuid().ToString(),
                                leaf = true,
                                parentId = aspect.id,
                                text = q.Title,
                                children = new List<GetProjectTaskTreeOutPut>()
                            };
                            aspect.children.Add(qs);
                        }
                    }
                }
            }

            outPut.tree = tree;

            return outPut;
        }

        public List<ProjectTask> Get(string txt)
        {
            List<ProjectTask> ts = new List<ProjectTask>();

            string route = string.Empty;
            string step = string.Empty;
            string dept = string.Empty;

            var lines = txt.Split(System.Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            foreach (var item in lines)
            {
                var tmp = item.Trim();


                if (tmp.StartsWith("Route", StringComparison.CurrentCultureIgnoreCase))
                {
                    if (tmp.IndexOf('：') == 5 || tmp.IndexOf(':') == 5)
                    {
                        route = tmp.Remove(0, 6).Trim();
                    }
                }

                if (tmp.StartsWith("Step", StringComparison.CurrentCultureIgnoreCase))
                {
                    if (tmp.IndexOf('：') == 4 || tmp.IndexOf(':') == 4)
                    {
                        step = tmp.Remove(0, 5).Trim();
                    }
                }
                if (tmp.EndsWith("方面：") || tmp.EndsWith("方面:"))
                {
                    dept = tmp.Remove(tmp.IndexOf("方面"));
                }

                if (tmp.StartsWith("问题"))
                {
                    if (tmp.IndexOf('：') > 2 || tmp.IndexOf(':') > 2)
                    {
                        ProjectTask t = new ProjectTask();
                        t.Route = route;
                        t.Dept = dept;
                        t.Step = step;
                        t.Title = tmp;
                        ts.Add(t);
                    }
                }
            }
            return ts;
        }


        public List<MyCompanyName.AbpZeroTemplate.Gantt.Dto.GetTaskOutPut> GetAllTasks()
        {
            var tasks = _projectTaskManager._projectTaskRepository.GetAllList();
            var results = tasks.Select(x => new MyCompanyName.AbpZeroTemplate.Gantt.Dto.GetTaskOutPut()
            {
                Id = x.Id,
                ParentId = 0,
                Title = x.Title,
                Describe = "",
                Deliverydate = x.PlanFinshTime.ToString("yyyy-MM-dd"),
                Progress = 0,
                Participants = "",
                //Flags = x.Color,
                Subtasks = ""
            }).ToList();
            return results;
        }


        public List<GetProjectTaskOutPut> GetTasks(GetProjectTaskInPut input)
        {
            List<GetProjectTaskOutPut> results = new List<GetProjectTaskOutPut>();

            var userId = AbpSession.GetUserId();
            var list = _projectTaskManager._projectTaskRepository.GetAll().OrderByDescending(x => x.Priority)
                .Where(x => x.ProjectId == input.ProjectId && !x.IsDeleted)
                .WhereIf(!string.IsNullOrEmpty(input.Route), x => x.Route.Contains(input.Route))
                .WhereIf(!string.IsNullOrEmpty(input.Dept), x => x.Dept.Contains(input.Dept))
                .WhereIf(!string.IsNullOrEmpty(input.Tags), x => x.Tags.Contains(input.Tags));

            if (input.ViewArchived)
            {
                list = list.Where(x => x.IsArchived);
            }
            else
            {
                list = list.Where(x => !x.IsArchived);
            }

            if (!string.IsNullOrEmpty(input.StartTime))
            {
                var st = DateTime.Parse(input.StartTime);
                list = list.Where(x => x.PlanFinshTime >= st);
            }
            if (!string.IsNullOrEmpty(input.EndTime))
            {
                var et = DateTime.Parse(input.EndTime).AddDays(1);
                list = list.Where(x => x.PlanFinshTime < et);
            }
            var qs = list.ToList();

            //问题查看权限 =    项目内共享 || 是问题参与成员  || 问题圈(成员圈|问题自定义圈)=当前用户圈
            //             =    查看所有 + 回答  + 关注|取消关注
            //问题编辑权限 =    执行者 = 编辑子任务 + 标志已完成

            var 项目问题超级权限 = _permissionService.HasPermission(userId, input.ProjectId, ProjectFunctions.项目问题超级权限);
            var 项目问题查看所有 = 项目问题超级权限 || _permissionService.HasPermission(userId, input.ProjectId, ProjectFunctions.项目问题查看所有);
            var hasTaskFollower = 项目问题超级权限 || _permissionService.HasPermission(userId, input.ProjectId, ProjectFunctions.项目问题关注);
            var hasTaskArchived = 项目问题超级权限 || _permissionService.HasPermission(userId, input.ProjectId, ProjectFunctions.项目问题归档);

            var projectSubTasks = _projectTaskManager._projectTaskSubTaskRepository.GetAll().Where(q => q.ProjectId == input.ProjectId).ToList();
            var projectFollower = _projectTaskManager._projectTaskFollowerRepository.GetAll().Where(m => m.ProjectId == input.ProjectId).ToList();
            var projectMembers = _projectTaskManager._projectTaskMemberRepository.GetAll().Where(m => m.ProjectId == input.ProjectId).ToList();

            foreach (var task in qs)
            {
                var members = projectMembers.Where(a => a.ProjectTaskId == task.Id).ToList();
                bool hasView = HasTaskRead(task, members, 项目问题超级权限, 项目问题查看所有);
                if (!hasView)
                {
                    continue;
                }

                var subTasks = projectSubTasks.Where(q => q.ProjectTaskId == task.Id).ToList();
                var isFollower = projectFollower.Any(m => m.ProjectTaskId == task.Id && m.UserId == userId);
                var outPut = new GetProjectTaskOutPut()
                {
                    Title = task.Title,
                    Id = task.Id,
                    HasTaskFollower = hasTaskFollower,
                    HasTaskArchived = hasTaskArchived,
                    Dept = task.Dept,
                    Priority = task.Priority,
                    IsArchived = task.IsArchived,
                    IsFinsh = task.IsFinsh,
                    IsFollower = isFollower,
                    FinshSubTask = subTasks.Where(m => m.Completed).Count(),
                    SubTask = subTasks.Count,
                    Members = string.Join(",", members.Select(q => q.User.Name)),
                    IsMember = 项目问题超级权限
                    || task.CreatorUserId == userId  // 创建者总是可以改。和任务成员一样。
                    || members.Any(q => q.UserId == userId),
                    PlanFinshTime = task.PlanFinshTime.ToString("yyyy-MM-dd"),
                    ProjectId = task.ProjectId,
                    range = task.Range,
                    Route = task.Route,
                    Step = task.Step,
                    Tags = task.Tags
                };
                results.Add(outPut);

            }
            return results;
        }

        /// <summary>
        /// 是否有任务的查看权限
        /// </summary>
        /// <param name="taskInfo"></param>
        /// <param name="members"></param>
        /// <param name="项目问题超级权限"></param>
        /// <param name="项目问题查看所有"></param>
        /// <returns></returns>
        private bool HasTaskRead(ProjectTask taskInfo, List<ProjectTaskMember> members, bool 项目问题超级权限, bool 项目问题查看所有)
        {
            if (项目问题查看所有 || 项目问题超级权限)
            {
                return true;
            }

            var userId = AbpSession.GetUserId();

            if (taskInfo.CreatorUserId == userId)
            {
                // 创建者总是可见
                return true;
            }

            // 任务成员可见
            if (members.Any(x => x.UserId == userId && x.ProjectTaskId == taskInfo.Id))
            {
                return true;
            }

            #region 圈的权限

            // 用户 圈
            var currentUserQuanCodes = _UserQuanRepository.GetAll().Where(x => x.UserId == userId).Select(x => x.QuanCode).ToList();
            if (currentUserQuanCodes == null || currentUserQuanCodes.Count == 0)
            {
                return false;
            }

            // 任务 圈
            List<string> taskQuanCodes;
            if (taskInfo.UsedMemberQuan)
            {
                var uids = members.Select(x => x.UserId).ToList();
                taskQuanCodes = _UserQuanRepository.GetAll().Where(x => uids.Contains(x.UserId)).Select(x => x.QuanCode).ToList();
            }
            else
            {
                taskQuanCodes = _taskQuanRepository.GetAll().Where(x => x.TaskId == taskInfo.Id).Select(x => x.QuanCode).ToList();
            }
            if (taskQuanCodes == null || taskQuanCodes.Count == 0)
            {
                return false;
            }

            foreach (var taskQuanCode in taskQuanCodes)
            {
                foreach (var currentUserQuanCode in currentUserQuanCodes)
                {
                    if (taskQuanCode.StartsWith(currentUserQuanCode))
                    {
                        return true;
                    }
                }
            }
            #endregion


            return false;
        }



        public async System.Threading.Tasks.Task UploadReply()
        {
            var projectTaskId = HttpContext.Current.Request.Form["projectTaskId"];
            var file = HttpContext.Current.Request.Files[0];
            if (file.ContentLength == 0)
            {
                throw new Abp.UI.UserFriendlyException("系统提示", "文件为空");
            }
            var fileBase = new HttpPostedFileWrapper(file) as HttpPostedFileBase;
            Guid fileGuid = Abp.GridFS.GridFSHelper.Upload(fileBase, AbpSession.GetUserId().ToString());
            await _projectTaskManager._projectTaskAttachmentRepository.InsertAsync(new ProjectTaskAttachment()
            {
                FullUrl = fileGuid.ToString(),
                Name = System.IO.Path.GetFileName(fileBase.FileName),
                ProjectTaskId = int.Parse(projectTaskId)
            });
        }


        public List<GetProjectTaskReplyOutPut> GetReplys(int projectTaskId)
        {
            List<GetProjectTaskReplyOutPut> result = new List<GetProjectTaskReplyOutPut>();
            var list = _projectTaskManager._projectTaskAttachmentRepository.GetAll().Where(x => x.ProjectTaskId == projectTaskId).OrderByDescending(x => x.CreationTime).ToList();
            foreach (var item in list)
            {
                result.Add(new GetProjectTaskReplyOutPut()
                {
                    Name = item.Name,
                    Note = item.Note,
                    IsDownLoad = string.IsNullOrEmpty(item.FullUrl) ? false : true,
                    FullPath = item.FullUrl,
                    CreateBy = UserManager.Users.Where(x => x.Id == item.CreatorUserId).SingleOrDefault().Name,
                    CreateOn = item.CreationTime.ToString("yyyy-MM-dd")
                });
            }
            return result;
        }





        public async System.Threading.Tasks.Task SetFinsh(int projectTaskId)
        {
            var t = await _projectTaskManager._projectTaskRepository.GetAsync(projectTaskId);
            t.IsFinsh = !t.IsFinsh;
            t.ActualFinshTime = DateTime.Now;

            //SendEmails(projectTaskId, "系统推送", string.Format("项目问题{0}被标记为已完成", t.Title));
        }


        public async System.Threading.Tasks.Task DeleteTask(int projectTaskId)
        {
            var task = await _projectTaskManager._projectTaskRepository.GetAsync(projectTaskId);
            await _projectTaskManager._projectTaskAttachmentRepository.DeleteAsync(x => x.ProjectTaskId == projectTaskId);
            await _projectTaskManager._projectTaskRepository.DeleteAsync(projectTaskId);
            await operationLogManager.Create(task.ProjectId, "项目任务删除", HostOperation.项目, "");

            //SendEmails(projectTaskId, "系统推送", string.Format("项目问题{0}被删除了", task.Title));

        }

        [UnitOfWork(isTransactional: false)]
        public void GetExport(GetExportInPut input)
        {
            var userId = AbpSession.GetUserId();
            var project = _projectManager.projectRepository.Get(input.projectId);
            var product = _productRepository.GetAll().Where(x => x.Code == project.ProductNo).FirstOrDefault();
            Abp.Mtrl.Material substance = new Abp.Mtrl.Material();
            if (product != null && product.SubstanceId > 0)
            {
                substance = _substanceManager.Get(product.SubstanceId);
            }

            var exportInfo = new ProjectExportInfo()
            {
                Id = project.Id,
                CAS = substance.CASNo,
                ChemicalName = substance.EnName,
                CustomerCode = project.CustomeCode,
                Challenges = "",
                Deliverables = "",
                Discussions = "",
                Duration = "",
                Gantt = "",
                Goals = "",
                Img = substance.ImgFile,
                NextPlan = "",
                ProjectCode = project.ProjectNo,
                ProjectLeader = project.PM,
                Results = "",
                Tags = new List<TagInfo>(),
                Status = project.Status.ToString(),
                Summary = "",
                SyntheticScheme = "",
                Timelines = ""
            };

            var year = DateTime.Now.Year;
            var week = DateHelper.GetWeek(DateTime.Now);




            var list = _projectTaskManager._projectTaskRepository.GetAll().OrderByDescending(x => x.Priority)
              .Where(x => x.ProjectId == input.projectId && !x.IsDeleted)
              .WhereIf(!string.IsNullOrEmpty(input.route), x => x.Route.Contains(input.route))
              .WhereIf(!string.IsNullOrEmpty(input.dept), x => x.Dept.Contains(input.dept))
              .WhereIf(!string.IsNullOrEmpty(input.tags), x => x.Tags.Contains(input.tags));

            if (!string.IsNullOrEmpty(input.startTime))
            {
                var st = DateTime.Parse(input.startTime);
                list = list.Where(x => x.PlanFinshTime >= st);
            }
            if (!string.IsNullOrEmpty(input.endTime))
            {
                var et = DateTime.Parse(input.endTime).AddDays(1);
                list = list.Where(x => x.PlanFinshTime < et);
            }

            var taskIds = list.Select(x => x.Id);

            var tasks = _projectTaskManager._projectTaskRepository.GetAll()
                .OrderBy(x => x.Id)
                .Where(x => (x.ProjectId == input.projectId && !x.IsFinsh) || taskIds.Contains(x.Id))//未完成的，总是给导出来。
                .ToList();


            var 项目问题超级权限 = _permissionService.HasPermission(userId, input.projectId, ProjectFunctions.项目问题超级权限);
            var 项目问题查看所有 = 项目问题超级权限 || _permissionService.HasPermission(userId, input.projectId, ProjectFunctions.项目问题查看所有);

            var projectMembers = _projectTaskManager._projectTaskMemberRepository.GetAll().Where(m => m.ProjectId == input.projectId).ToList();
            var authTasks = new List<ProjectTask>();
            foreach (var task in tasks)
            {
                var members = projectMembers.Where(a => a.ProjectTaskId == task.Id).ToList();
                bool hasView = HasTaskRead(task, members, 项目问题超级权限, 项目问题查看所有);
                if (!hasView)
                {
                    continue;
                }
                authTasks.Add(task);
            }


            #region 按照Tag分组汇总数据
            /*
             * 有标签的和无标签的，分为2组数据；
             */

            var tagStrLst = authTasks.Select(x => x.Tags).ToList();
            List<string> tags = GetTags(tagStrLst).Select(x => x.Key).ToList();

            int tagTemp = 1;
            int routeTemp = 10000;
            int stepTemp = 20000;
            int deptTemp = 30000;
            int qTemp = 40000;

            var addTaskIds = new List<int>();
            foreach (var tag in tags)
            {
                tagTemp++;
                var _tasks = authTasks.Where(x => x.Tags.Contains(tag)).ToList();
                addTaskIds.AddRange(_tasks.Select(x => x.Id));
                var _tagInfo = new TagInfo()
                {
                    Id = tagTemp.ToString(),
                    Name = tag,
                    Routes = new List<RouteInfo>()
                };
                TagRouteStepTask(ref routeTemp, ref stepTemp, ref deptTemp, ref qTemp, _tasks, _tagInfo);
                exportInfo.Tags.Add(_tagInfo);
            }
            var otherTasks = authTasks.Where(x => !addTaskIds.Contains(x.Id)).ToList();
            if (otherTasks.Count > 0)
            {
                tagTemp++;
                var _tagInfo = new TagInfo()
                {
                    Id = tagTemp.ToString(),
                    Name = "",
                    Routes = new List<RouteInfo>()
                };
                TagRouteStepTask(ref routeTemp, ref stepTemp, ref deptTemp, ref qTemp, otherTasks, _tagInfo);
                exportInfo.Tags.Add(_tagInfo);
            }
            #endregion


            WordHelper helper = new WordHelper();
            string path = helper.Report(exportInfo, SaveFormat.Doc);

            var startIndex = path.LastIndexOf(@"\");
            string filename = path.Substring(startIndex + 1);
            ExcelHelper.ResponseFile(filename, path);
        }

        private void TagRouteStepTask(ref int routeTemp, ref int stepTemp, ref int deptTemp, ref int qTemp, List<ProjectTask> _tasks, TagInfo _tagInfo)
        {
            var routes = _tasks.GroupBy(x => x.Route).Select(x => x.Key);
            foreach (var item in routes)
            {
                ++routeTemp;
                var route = new RouteInfo()
                {
                    Id = routeTemp.ToString(),
                    Name = item,
                    Steps = new List<StepInfo>()
                };
                _tagInfo.Routes.Add(route);
                var steps = _tasks.Where(x => x.Route == item).GroupBy(x => x.Step).Select(x => x.Key);
                foreach (var s in steps)
                {
                    ++stepTemp;
                    var step = new StepInfo()
                    {
                        Id = stepTemp.ToString(),
                        Aspects = new List<AspectInfo>(),
                        Name = s
                    };
                    route.Steps.Add(step);
                    var depts = _tasks.Where(x => x.Step == s && x.Route == item).GroupBy(x => x.Dept).Select(x => x.Key);
                    foreach (var d in depts)
                    {
                        ++deptTemp;
                        var aspect = new AspectInfo()
                        {
                            Id = deptTemp.ToString(),
                            Name = d,
                            Qas = new List<Qa>()
                        };
                        step.Aspects.Add(aspect);
                        var qus = _tasks.Where(x => x.Route == item && x.Step == s && x.Dept == d);
                        foreach (var q in qus)
                        {
                            ++qTemp;
                            var paths = _projectTaskManager._projectTaskAttachmentRepository.GetAll().Where(x => x.ProjectTaskId == q.Id).Select(x => x.FullUrl).ToList();
                            var notes = _projectTaskManager._projectTaskAttachmentRepository.GetAll().Where(x => x.ProjectTaskId == q.Id).Select(x => x.Note).ToList();
                            var t = new Qa()
                            {
                                Id = qTemp.ToString(),
                                Description = notes,
                                Question = q.Title,
                                AnswerResult = paths
                            };
                            aspect.Qas.Add(t);
                        }
                    }
                }
            }
        }

        public async Task EditTask(EditProjectTaskInPut input)
        {
            //string tags = "";
            //if (!string.IsNullOrEmpty(input.Tags))
            //{
            //    List<string> listTags = input.Tags.Split(new char[] { ',', '，', ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            //    tags = string.Join(",", listTags.Distinct());
            //}
            //if (input.Id > 0)
            //{
            //    var edit = await _projectTaskManager._projectTaskRepository.GetAsync(input.Id);
            //    edit.Dept = input.Dept;
            //    edit.Route = input.Route;
            //    edit.Step = input.Step;
            //    edit.Title = input.Title;
            //    edit.PlanFinshTime = input.PlanFinshTime;
            //    edit.Tags = tags;
            //    edit.Priority = input.Priority;
            //    edit.Range = input.Range;
            //    if (edit.Range == VisibleRange.项目内共享)
            //    {
            //        _projectTaskManager._projectTaskMemberRepository.Delete(x => x.ProjectTaskId == input.Id);
            //    }
            //    else
            //    {
            //        var members = _projectTaskManager._projectTaskMemberRepository.GetAll().Where(x => x.ProjectTaskId == input.Id)
            //            .Select(x => x.UserId).ToList();
            //        var adds = input.users.Where(x => !members.Contains(x));
            //        var dels = members.Where(x => !input.users.Contains(x));
            //        foreach (var userId in adds)
            //        {
            //            var member = new ProjectTaskMember()
            //            {
            //                ProjectId = input.ProjectId,
            //                ProjectTaskId = input.Id,
            //                UserId = userId
            //            };
            //            await _projectTaskManager._projectTaskMemberRepository.InsertAsync(member);
            //        }
            //        _projectTaskManager._projectTaskMemberRepository.Delete(x => dels.Contains(x.UserId) && x.ProjectTaskId == input.Id);
            //    }
            //    if (input.SubTasks != null)
            //    {
            //        foreach (var item in input.SubTasks)
            //        {
            //            if (item.Id > 0)
            //            {
            //                var sub = _projectTaskManager._projectTaskSubTaskRepository.Get(item.Id);
            //                sub.SubTitle = item.SubTitle;
            //                sub.Completed = item.Completed;
            //            }
            //            else
            //            {
            //                var subTask = new ProjectTaskSubTask()
            //                {
            //                    ProjectId = input.ProjectId,
            //                    ProjectTaskId = input.Id,
            //                    SubTitle = item.SubTitle,
            //                    Completed = item.Completed
            //                };
            //                await _projectTaskManager._projectTaskSubTaskRepository.InsertAsync(subTask);
            //            }
            //        }

            //        var subTasks = _projectTaskManager._projectTaskSubTaskRepository.GetAll().Where(x => x.ProjectTaskId == input.Id).Select(x => x.Id).ToList();
            //        var dels = subTasks.Where(x => !input.SubTasks.Select(m => m.Id).Contains(x));
            //        _projectTaskManager._projectTaskSubTaskRepository.Delete(x => dels.Contains(x.Id));
            //    }
            //}
            //else
            //{
            //    var task = new ProjectTask()
            //    {
            //        Dept = input.Dept,
            //        PlanFinshTime = input.PlanFinshTime,
            //        ProjectId = input.ProjectId,
            //        Route = input.Route,
            //        Step = input.Step,
            //        Tags = tags,
            //        UsedMemberQuan = true,
            //        Priority = input.Priority,
            //        Title = input.Title,
            //        Range = input.Range,
            //        Week = DateHelper.GetWeek(DateTime.Now),
            //        Year = DateTime.Now.Year,
            //        ActualFinshTime = DateTime.Now
            //    };
            //    var taskId = await _projectTaskManager._projectTaskRepository.InsertAndGetIdAsync(task);
            //    if (input.users != null)
            //    {
            //        foreach (var userId in input.users)
            //        {
            //            var member = new ProjectTaskMember()
            //            {
            //                ProjectId = input.ProjectId,
            //                ProjectTaskId = taskId,
            //                UserId = userId
            //            };
            //            await _projectTaskManager._projectTaskMemberRepository.InsertAsync(member);
            //        }
            //    }
            //    if (input.SubTasks != null)
            //    {
            //        foreach (var sub in input.SubTasks)
            //        {
            //            var subTask = new ProjectTaskSubTask()
            //            {
            //                OrderNo = 0,
            //                ProjectId = input.ProjectId,
            //                ProjectTaskId = taskId,
            //                SubTitle = sub.SubTitle,
            //                Completed = sub.Completed
            //            };
            //            await _projectTaskManager._projectTaskSubTaskRepository.InsertAsync(subTask);
            //        }
            //    }
            //}

            await operationLogManager.Create(input.ProjectId, "项目任务编辑", HostOperation.项目, Newtonsoft.Json.JsonConvert.SerializeObject(input));

        }


        public async Task<GetProjectTaskOutPut> Get(int projectTaskId)
        {
            var task = await _projectTaskManager._projectTaskRepository.GetAsync(projectTaskId);
            var model = task.MapTo<GetProjectTaskOutPut>();


            var member = _projectTaskManager._projectTaskMemberRepository.GetAll().Where(x => x.ProjectTaskId == projectTaskId);
            //任务成员
            model.Members = string.Join(",", member.Select(x => x.User.Name));
            model.MemberIds = member.Select(x => x.User.Id).ToList();
            //任务所在圈
            var qs = _taskQuanRepository.GetAll().Where(x => x.TaskId == projectTaskId).Select(m => m.QuanId).ToList();
            model.Quans = string.Join(",", _quanRepository.GetAll().Where(x => qs.Contains(x.Id)).Select(x => x.Name));

            model.QuanIds = qs.Select(m => new KeyValuePair<int, int>(m, 0)).ToList();

            //子任务
            model.Children = _projectTaskManager._projectTaskSubTaskRepository.GetAll().Where(x => x.ProjectTaskId == projectTaskId).ToList()
                .Select(m => new KeyValuePair<bool, string>(m.Completed, m.SubTitle)).ToList();
            model.Followers = string.Join(",", _projectTaskManager._projectTaskFollowerRepository.GetAll().Where(x => x.ProjectTaskId == projectTaskId).Select(m => m.User.Name));

            return model;
        }

        //[UnitOfWork(isTransactional: false)]
        public async Task CreateReply(CreateTaskReply input)
        {
            //var file = HttpContext.Current.Request.Files[0];
            //string path = "";
            //string name = "";
            //if (file.ContentLength > 0)
            //{
            //    var fileBase = new HttpPostedFileWrapper(file) as HttpPostedFileBase;
            //    path = Abp.GridFS.GridFSHelper.Upload(fileBase, AbpSession.GetUserId().ToString()).ToString();
            //    name = System.IO.Path.GetFileName(fileBase.FileName);
            //}
            //var projectTaskId = int.Parse(HttpContext.Current.Request.Form["projectTaskId"]);
            //var note = HttpContext.Current.Request.Form["note"];

            await _projectTaskManager._projectTaskAttachmentRepository.InsertAsync(new ProjectTaskAttachment()
            {
                FullUrl = input.FullPath,
                Name = input.Name,
                Note = input.Title,
                ProjectTaskId = input.ProjectTaskId
            });

            var task = await _projectTaskManager._projectTaskRepository.GetAsync(input.ProjectTaskId);
            //SendEmails(input.ProjectTaskId, "系统推送", string.Format("项目问题{0}添加了一个答案", task.Title));
            CreateTaskMail(input.ProjectTaskId, MailCatelog.项目任务更新通知);

            await operationLogManager.Create(task.ProjectId, "项目任务答复", HostOperation.项目, "");

        }


        public void GetDownTemplate()
        {
            ExcelHelper.ResponseFile("weekly_import.doc", @"App_Data\report_tpl\weekly_import.doc");
        }


        [UnitOfWork(isTransactional: false)]
        public async Task ImportConfirm(ProjectTaskImportConfirmInPut input)
        {
            foreach (var item in input.tasks)
            {
                var taskId = await _projectTaskManager._projectTaskRepository.InsertAndGetIdAsync(new ProjectTask()
                {
                    Dept = item.Dept,
                    ActualFinshTime = DateTime.Now,
                    PlanFinshTime = DateTime.Now,
                    Range = VisibleRange.项目内共享,
                    Tags = "",
                    UsedMemberQuan = true,
                    ProjectId = input.projectId,
                    Route = item.Route,
                    Step = item.Step,
                    Title = item.Title,
                    Year = DateTime.Now.Year,
                    Week = DateHelper.GetWeek(DateTime.Now)
                });
            }
        }


        public List<KeyValuePair<string, int>> GetTaskTags(int projectId)
        {
            List<string> cols = new List<string>();
            var tags = _projectTaskManager._projectTaskRepository.GetAll().Where(x => x.ProjectId == projectId).Select(x => x.Tags).ToList();
            return GetTags(tags);
        }

        private static List<KeyValuePair<string, int>> GetTags(List<string> tags)
        {
            List<string> cols = new List<string>();
            foreach (var item in tags)
            {
                var strs = item.Split(new char[] { ',', '，', ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                cols.AddRange(strs);
            }

            var list = cols.Select(x => new KeyValuePair<string, int>(x, 1)).ToList();
            return list.Distinct().OrderBy(x => x.Key).ToList();
        }


        public List<GetSubTaskOutPut> GetSubTasks(int taskId)
        {
            var result = _projectTaskManager._projectTaskSubTaskRepository.GetAll().Where(x => x.ProjectTaskId == taskId)
                .Select(x => new GetSubTaskOutPut()
                {
                    Id = x.Id,
                    Completed = x.Completed,
                    SubTitle = x.SubTitle
                })
                .ToList();
            return result;
        }

        public async Task<List<GetProjectTeamCheckedTreeDto>> GetRoleUserTree(int projectId, int taskId)
        {
            List<GetProjectTeamCheckedTreeDto> puts = new List<GetProjectTeamCheckedTreeDto>();
            var teams = _projectManager.projectTeamRepository.GetAll().Where(x => x.ProjectId == projectId).ToList();
            var roles = teams.GroupBy(x => x.ProjectRoleId).Select(x => x.Key);

            var members = _projectTaskManager._projectTaskMemberRepository.GetAll().Where(x => x.ProjectTaskId == taskId).Select(x => x.UserId).ToList();

            foreach (var roleId in roles)
            {
                var role = await _projectManager.projectRoleInfoRepository.GetAsync(roleId);
                var node = new GetProjectTeamCheckedTreeDto()
                {
                    @checked = false,
                    expanded = true,
                    children = new List<GetProjectTeamCheckedTreeDto>(),
                    id = (roleId * -1).ToString(),
                    leaf = false,
                    parentId = "0",
                    text = role.RoleName
                };
                var users = teams.Where(x => x.ProjectRoleId == role.Id).Select(x => x.UserId);
                foreach (var userId in users)
                {
                    var user = UserManager.Users.Where(x => x.Id == userId).SingleOrDefault();
                    var child = new GetProjectTeamCheckedTreeDto()
                    {
                        @checked = members.Contains(userId),
                        expanded = true,
                        children = null,
                        id = userId.ToString(),
                        leaf = true,
                        parentId = node.id,
                        text = user.Name
                    };
                    node.children.Add(child);
                }
                puts.Add(node);
            }
            return puts;
        }


        public async Task SetArchived(int projectTaskId)
        {
            var task = await _projectTaskManager._projectTaskRepository.GetAsync(projectTaskId);
            task.IsArchived = !task.IsArchived;

            //SendEmails(projectTaskId, "系统推送", string.Format("项目问题{0}被标记为归档", task.Title));
        }


        public async Task FollowerTask(int projectTaskId, int projectId)
        {
            await SetTaskFollower(projectTaskId, projectId);
        }


        public async Task SetTaskFollower(int projectTaskId, int projectId)
        {
            var userId = AbpSession.GetUserId();
            if (!_projectTaskManager._projectTaskFollowerRepository.GetAll().Any(x => x.ProjectTaskId == projectTaskId && x.UserId == userId))
            {
                var task = await _projectTaskManager._projectTaskRepository.GetAsync(projectTaskId);
                await _projectTaskManager._projectTaskFollowerRepository.InsertAsync(new ProjectTaskFollower()
                {
                    ProjectId = projectId,
                    ProjectTaskId = projectTaskId,
                    UserId = userId
                });
                var user = UserManager.Users.Where(x => x.Id == userId).SingleOrDefault();
                //SendEmails(projectTaskId, "系统推送", string.Format("项目问题{0}被标{1}关注了", task.Title, user.Name));
            }
        }



        public List<GetWorkProjectTaskOutPut> GetMyFollower()
        {
            var userId = AbpSession.GetUserId();
            List<GetWorkProjectTaskOutPut> result = new List<GetWorkProjectTaskOutPut>();
            var alls = _projectTaskManager._projectTaskFollowerRepository.GetAll().Where(x => x.UserId == userId && !x.ProjectTask.IsFinsh)
                .ToList();

            foreach (var x in alls)
            {
                var project = _projectManager.projectRepository.Get(x.ProjectId);
                var put = new GetWorkProjectTaskOutPut()
                {
                    FollowerId = x.Id,
                    ProjectId = x.ProjectId,
                    ProjectName = project.ProjectName,
                    ProjectNo = project.ProjectNo,
                    ProjectTaskId = x.ProjectTaskId,
                    Title = x.ProjectTask.Title,
                    PlanFinshTime = x.ProjectTask.PlanFinshTime.ToString("yyyy-MM-dd"),
                    Members = string.Join(",", _projectTaskManager._projectTaskMemberRepository.GetAll().Where(m => m.ProjectTaskId == x.ProjectTaskId).Select(q => q.User.Name))
                };
                result.Add(put);
            }
            return result;
        }


        public List<GetWorkProjectTaskOutPut> GetMyWork()
        {
            var userId = AbpSession.GetUserId();
            List<GetWorkProjectTaskOutPut> result = new List<GetWorkProjectTaskOutPut>();
            var alls = _projectTaskManager._projectTaskMemberRepository.GetAll().Where(x => x.UserId == userId && !x.ProjectTask.IsFinsh)
                .ToList();
            foreach (var x in alls)
            {
                var project = _projectManager.projectRepository.Get(x.ProjectId);
                var put = new GetWorkProjectTaskOutPut()
                {
                    ProjectId = x.ProjectId,
                    ProjectName = project.ProjectName,
                    ProjectNo = project.ProjectNo,
                    ProjectTaskId = x.ProjectTaskId,
                    Title = x.ProjectTask.Title,
                    PlanFinshTime = x.ProjectTask.PlanFinshTime.ToString("yyyy-MM-dd"),
                    Members = string.Join(",", _projectTaskManager._projectTaskMemberRepository.GetAll().Where(m => m.ProjectTaskId == x.ProjectTaskId).Select(q => q.User.Name))
                };
                result.Add(put);
            }
            return result;
        }


        public async Task RemoveFollower(int followerId)
        {
            await _projectTaskManager._projectTaskFollowerRepository.DeleteAsync(followerId);
        }


        public async Task BatchEditTask(BatchEditTaskInPut input)
        {
            var userId = AbpSession.GetUserId();
            int projectId = 0;
            foreach (var item in input.datas)
            {
                var task = await _projectTaskManager._projectTaskRepository.GetAsync(item.Id);

                if (item.IsFinsh == true && task.IsFinsh == false)
                {
                    CreateTaskMail(item.Id, MailCatelog.项目任务完成通知);
                }

                task.IsArchived = item.IsArchived;
                task.IsFinsh = item.IsFinsh;
                task.Priority = item.Priority;
                task.PlanFinshTime = item.PlanFinshTime;

                if (projectId == 0)
                {
                    projectId = task.ProjectId;
                }

                if (item.IsFollower)
                {
                    if (!_projectTaskManager._projectTaskFollowerRepository.GetAll().Any(x => x.ProjectTaskId == item.Id && x.UserId == userId))
                    {
                        await _projectTaskManager._projectTaskFollowerRepository.InsertAsync(new ProjectTaskFollower()
                        {
                            ProjectId = task.ProjectId,
                            ProjectTaskId = task.Id,
                            UserId = userId
                        });
                    }
                }
                else
                {
                    _projectTaskManager._projectTaskFollowerRepository.Delete(x => x.ProjectTaskId == task.Id && x.UserId == userId);
                }
            }


            await operationLogManager.Create(projectId, "项目任务编辑", HostOperation.项目, Newtonsoft.Json.JsonConvert.SerializeObject(input));

        }

        private void CreateTaskMail(int projectTaskId, MailCatelog catelog)
        {
            var followers = _projectTaskManager._projectTaskFollowerRepository.GetAll().Where(x => x.ProjectTaskId == projectTaskId).Select(x => x.UserId).ToList();
            var members = _projectTaskManager._projectTaskMemberRepository.GetAll().Where(x => x.ProjectTaskId == projectTaskId).Select(x => x.UserId).ToList();

            var receiverIds = new List<long>();
            receiverIds.AddRange(followers);
            receiverIds.AddRange(members);
            receiverIds = receiverIds.Distinct().ToList();
            var task = _projectTaskManager._projectTaskRepository.Get(projectTaskId);
            var p = _projectManager.projectRepository.Get(task.ProjectId);
            Dictionary<string, string> dic = new Dictionary<string, string>();
            dic["问题"] = task.Title;
            dic["项目名称"] = p.ProjectName;
            dic["项目编号"] = p.ProjectNo;
            _mailManager.CreateProTaskMailRecord("", dic, catelog, receiverIds);

        }

        public async Task EditTaskQuan(EditProjectTaskInPut input)
        {
            bool isFinish = false;

            string tags = "";
            if (!string.IsNullOrEmpty(input.Tags))
            {
                List<string> listTags = input.Tags.Split(new char[] { ',', '，', ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                tags = string.Join(",", listTags.Distinct());
            }
            if (input.Id == 0)
            {
                var task = new Project.ProjectTask()
                {
                    Dept = input.Dept,
                    PlanFinshTime = input.PlanFinshTime,
                    ProjectId = input.ProjectId,
                    Route = input.Route,
                    Step = input.Step,
                    Tags = tags,
                    UsedMemberQuan = true,
                    Priority = input.Priority,
                    Title = input.Title,
                    Range = VisibleRange.指定成员,
                    Week = DateHelper.GetWeek(DateTime.Now),
                    Year = DateTime.Now.Year,
                    ActualFinshTime = DateTime.Now
                };
                input.Id = await _projectTaskManager._projectTaskRepository.InsertAndGetIdAsync(task);
            }
            else
            {
                var task = _projectTaskManager._projectTaskRepository.Get(input.Id);
                task.Title = input.Title;
                task.Tags = input.Tags;
                task.PlanFinshTime = input.PlanFinshTime;
                task.Priority = input.Priority;
                task.Route = input.Route;
                task.Step = input.Step;
                task.Dept = input.Dept;

                if (input.Completed)
                {
                    if (!task.IsFinsh)
                    {
                        isFinish = true;
                    }


                    task.IsFinsh = true;
                }

                if (!string.IsNullOrEmpty(input.isFollower))
                {
                    bool 关注 = input.isFollower.Equals("关注");
                    if (关注)
                    {
                        await SetTaskFollower(task.Id, task.ProjectId);
                    }
                    else
                    {
                        var userId = AbpSession.GetUserId();
                        _projectTaskManager._projectTaskFollowerRepository.Delete(m => m.ProjectTaskId == task.Id && m.UserId == userId);
                    }
                }

                _projectTaskManager._projectTaskSubTaskRepository.Delete(m => m.ProjectTaskId == input.Id);
                _taskQuanRepository.Delete(m => m.TaskId == input.Id);
                _projectTaskManager._projectTaskMemberRepository.Delete(x => x.ProjectTaskId == input.Id);
            }
            if (input.ChildTask != null)
            {
                foreach (var item in input.ChildTask)
                {
                    var subTask = new Project.ProjectTaskSubTask()
                    {
                        ProjectId = input.ProjectId,
                        ProjectTaskId = input.Id,
                        SubTitle = item,
                        Completed = input.IsCompleted.Any(x => x == item)
                    };
                    await _projectTaskManager._projectTaskSubTaskRepository.InsertAsync(subTask);
                }
            }


            List<int> adds = new List<int>();
            if (input.Quans != null)
            {
                foreach (var item in input.Quans)
                {
                    if (!input.Quans.Any(x => x.Key == item.Value))
                    {
                        adds.Add(item.Key);
                    }
                }
            }


            foreach (var quanId in adds)
            {
                var quan = _quanRepository.Get(quanId);
                var taskQuan = new TaskQuan()
                {
                    ProjectId = input.ProjectId,
                    QuanId = quanId,
                    TaskId = input.Id,
                    QuanCode = quan.Code
                };
                await _taskQuanRepository.InsertAsync(taskQuan);
            }

            foreach (var userId in input.members)
            {
                var member = new ProjectTaskMember()
                {
                    ProjectId = input.ProjectId,
                    ProjectTaskId = input.Id,
                    UserId = userId
                };
                await _projectTaskManager._projectTaskMemberRepository.InsertAsync(member);
            }

            if (isFinish)
            {
                CreateTaskMail(input.Id, MailCatelog.项目任务完成通知);
            }
        }

        /// <summary>
        /// 到期未完成的邮件提醒
        /// </summary>
        public void GetMailTaskToClose()
        {
            DateTime dt = DateTime.Now.Date;
            var tasks = _projectTaskManager._projectTaskRepository.GetAll().Where(x => x.IsDeleted == false
                 && x.IsArchived == false && x.PlanFinshTime <= dt).OrderBy(x => x.PlanFinshTime).ToList();

            var projectIds = tasks.Select(x => x.ProjectId).Distinct().ToList();
            System.Text.StringBuilder sb = new StringBuilder();
            foreach (var projectId in projectIds)
            {
                var p = _projectManager.projectRepository.Get(projectId);
                var _tasks = tasks.Where(x => x.ProjectId == projectId).ToList();
                sb = new StringBuilder();
                sb.Append(@"<style type='text/css'> 
                                table 
                                { 
                                border-collapse: collapse; 
                                border: none; 
                                width: 200px; 
                                } 
                                td 
                                { 
                                border: solid #000 1px; 
                                } 
                                </style> ");
                sb.Append("<table border=1>");
                sb.Append("<tr><td>问题</td><td>计划完成</td><td>执行人</td></tr>");
                foreach (var item in _tasks)
                {
                    string member = string.Join(",", _projectTaskManager._projectTaskMemberRepository.GetAll()
                          .Where(m => m.ProjectTaskId == item.Id && m.IsDeleted == false).Select(x => x.User.Name));

                    sb.Append(string.Format("<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>"
                   , item.Title, item.PlanFinshTime.ToString("yyyy-MM-dd")
                   , member));
                }
                sb.Append("</table>");
                Dictionary<string, string> dic = new Dictionary<string, string>();
                dic["待归档任务明细"] = sb.ToString();
                dic["待归档任务数"] = _tasks.Count.ToString();
                dic["项目编号"] = p.ProjectNo;
                _mailManager.CreateMailRecord(dic, MailCatelog.项目任务到期未归档通知, projectId);
            }
        }

        public int GetNewTaskCount(int projectId, DateTime dts)
        {
            return _projectTaskManager._projectTaskRepository.GetAll().Where(x => x.ProjectId == projectId && x.CreationTime >= dts).Count();
        }
        public int GetCloseTaskCount(int projectId, DateTime dts)
        {
            return _projectTaskManager._projectTaskRepository.GetAll().Where(x => x.ProjectId == projectId && x.IsArchived && x.LastModificationTime >= dts).Count();
        }

    }
}
